package com.minio.demo.utils;

import com.j256.simplemagic.ContentInfo;
import com.j256.simplemagic.ContentInfoUtil;
import io.minio.*;
import io.minio.http.Method;

import java.io.InputStream;
import java.util.UUID;

public class MinioUtils {

    private final String ENDPOINT;

    private final String ACCESS_KEY;

    private final String SECRET_KEY;

    public MinioUtils(String endpoint , String accessKey , String secretKey){
        this.ENDPOINT = endpoint;
        this.ACCESS_KEY = accessKey;
        this.SECRET_KEY = secretKey;
    }

    private static final ContentInfoUtil contentInfoUtil = new ContentInfoUtil();

    /**
     * 文件url前半段
     * @param bucket 桶
     * @return 前半段
     */
    private String getObjectPrefixUrl(String bucket) {
        return String.format("%s/%s/", ENDPOINT, bucket);
    }

    /**
     * 上传本地文件
     * @param bucket    桶
     * @param storePath 存储路径
     * @param filePath  文件路径
     * @return 文件url
     */
    public String uploadFile(
            String bucket,
            String storePath,
            String filePath) throws Exception {
        MinioClient client = MinioClient.builder()
                .endpoint(ENDPOINT).credentials(ACCESS_KEY, SECRET_KEY).build();
        String[] ss = filePath.split("/");
        String objectKey = getObjectKey(storePath, ss[ss.length-1]);
        ContentInfo contentInfo = contentInfoUtil.findMatch(filePath);
        client.uploadObject(UploadObjectArgs.builder()
                .bucket(bucket)
                .object(objectKey)
                .contentType(contentInfo.getMimeType())
                .filename(filePath)
                .build());

        return getObjectPrefixUrl(bucket) + objectKey;
    }

    /**
     * 流式上传文件
     * @param bucket      桶
     * @param storePath   存储路径
     * @param fileName    文件名
     * @param inputStream 文件输入流
     * @param contentType 文件类型
     * @return 文件url
     */
    public String uploadInputStream(
            String bucket,
            String storePath,
            String fileName,
            String contentType ,
            InputStream inputStream
    ) throws Exception {
        MinioClient client = MinioClient.builder()
                .endpoint(ENDPOINT)
                .credentials(ACCESS_KEY, SECRET_KEY).build();
        String objectKey = getObjectKey(storePath, fileName);
        client.putObject(
                PutObjectArgs.builder()
                        .bucket(bucket)
                        .object(objectKey)
                        .contentType(contentType)
                        .stream(inputStream,inputStream.available(),-1)
                        .build());
        return getObjectPrefixUrl(bucket) + objectKey;
    }

    /**
     * 下载文件
     * @param bucket    桶
     * @param objectKey 文件key
     * @return 文件流
     */
    public InputStream download(
            String bucket,
            String objectKey) throws Exception {
        MinioClient client = MinioClient.builder()
                .endpoint(ENDPOINT).credentials(ACCESS_KEY, SECRET_KEY).build();

        return client.getObject(GetObjectArgs.builder().bucket(bucket).object(objectKey).build());
    }

    public InputStream download(String url) throws Exception {
        String path = url.replace(ENDPOINT + "/", "");
        String[] split = path.split("/");
        StringBuilder objectKey = new StringBuilder(split[1]);
        for (int i = 2; i < split.length; i++) {
            objectKey.append("/").append(split[i]);
        }
        return download(split[0], objectKey.toString());
    }

    /**
     * 文件复制
     * @param sourceBucket    源桶
     * @param sourceObjectKey 源文件key
     * @param bucket          目标桶
     * @param objectKey       目标文件key
     * @return 新文件url
     */
    public String copyFile(
            String sourceBucket,
            String sourceObjectKey,
            String bucket,
            String objectKey)
            throws Exception {
        MinioClient client = MinioClient.builder()
                .endpoint(ENDPOINT).credentials(ACCESS_KEY, SECRET_KEY).build();
        CopySource source = CopySource.builder()
                .bucket(sourceBucket).object(sourceObjectKey).build();
        client.copyObject(
                CopyObjectArgs.builder()
                        .bucket(bucket).object(objectKey).source(source).build());

        return getObjectPrefixUrl(bucket) + objectKey;
    }

    /**
     * 删除文件
     * @param bucket    桶
     * @param objectKey 文件key
     */
    public void deleteFile(
            String bucket,
            String objectKey) throws Exception {
        MinioClient client = MinioClient.builder()
                .endpoint(ENDPOINT).credentials(ACCESS_KEY, SECRET_KEY).build();
        client.removeObject(RemoveObjectArgs.builder().bucket(bucket).object(objectKey).build());
    }

    /*
     * @param url 文件全路径
     */
    public void deleteFile(String url) throws Exception {
        String path = url.replace(ENDPOINT + "/", "");
        String[] split = path.split("/");
        StringBuilder objectKey = new StringBuilder(split[1]);
        for (int i = 2; i < split.length; i++) {
            objectKey.append("/").append(split[i]);
        }
        deleteFile(split[0], objectKey.toString());
    }

    /**
     * 获取文件签名url
     * @param bucket    桶
     * @param objectKey 文件key
     * @param expires   签名有效时间 单位秒
     * @return 文件签名地址
     */
    public String getSignedUrl(
            String bucket,
            String objectKey,
            int expires) throws Exception {

        MinioClient client = MinioClient.builder().endpoint(ENDPOINT).credentials(ACCESS_KEY, SECRET_KEY).build();
        return client.getPresignedObjectUrl(GetPresignedObjectUrlArgs.builder().method(Method.GET).bucket(bucket)
                .object(objectKey).expiry(expires).build());

    }

    private String genFileName(String originalFilename) {
        // 获取后缀名
        String ext = originalFilename.substring(originalFilename.lastIndexOf("."));
        // 使用uuid生成随机名
        String uuid = UUID.randomUUID().toString().replaceAll("-", "");
        return uuid + ext;
    }

    private String getObjectKey(String storePath, String fileName) {
        String objectKey = "";
        if (storePath != null) {
            if (storePath.startsWith("/")) {
                storePath = storePath.substring(1);
            }
            if (storePath.endsWith("/")) {
                storePath = storePath.substring(0, storePath.length() - 1);
            }
            objectKey = storePath + "/" + genFileName(fileName);
        }
        return objectKey;
    }

}